package ar.edu.unlam.tpfinal.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import ar.edu.unlam.tpfinal.model.Address;
import ar.edu.unlam.tpfinal.model.Client;
import ar.edu.unlam.tpfinal.persistence.dao.AddressDAO;
import ar.edu.unlam.tpfinal.persistence.dao.ClientDAO;
import ar.edu.unlam.tpfinal.persistence.exceptions.PersistenceExceptionWrapper;
import ar.edu.unlam.tpfinal.service.ClientService;
import ar.edu.unlam.tpfinal.service.exceptions.ServiceException;
import ar.edu.unlam.tpfinal.struts.forms.AddressForm;
import ar.edu.unlam.tpfinal.struts.forms.ClientForm;

@Service(value="clientService")
public class ClientServiceImpl implements ClientService {

	@Autowired
	private ClientDAO clientDAO;
	
	@Autowired
	private AddressDAO addressDAO;
	
	// DI con Spring
	public void setClientDAO(ClientDAO clientDAO) {
		this.clientDAO = clientDAO;
	}
	
	public void setAddressDAO(AddressDAO addressDAO) {
		this.addressDAO = addressDAO;
	}

	@Override
	public void updateClient(ClientForm clientForm) throws ServiceException {
		try {
			Client client = clientDAO.findByOID(clientForm.getOid());
			merge(client, clientForm);
			clientDAO.save(client);
		} catch (PersistenceExceptionWrapper ex) {
			throw new ServiceException(ex);
		}	
	}
	
	@Override
	public void insertClient(ClientForm clientForm) throws ServiceException {
		try {
			Client client = getClientFromClientForm(clientForm);
			clientDAO.save(client);
		} catch (PersistenceExceptionWrapper ex) {
			throw new ServiceException(ex);
		}
	}
	
	@Override
	public void deleteClient(ClientForm clientForm) {
		try {
			Client client = clientDAO.findByOID(clientForm.getOid());
			clientDAO.delete(client);
		} catch (PersistenceExceptionWrapper ex) {
			throw new ServiceException(ex);
		}
	}

	@Override
	public ClientForm getClient(Long oid) throws ServiceException {
		try {
			Client client = clientDAO.findByOID(oid);
			ClientForm clientForm = getClientFormFromClient(client);
			return clientForm;
		} catch (PersistenceExceptionWrapper ex) {
			throw new ServiceException(ex);
		}
	}
	
	@Override
	public List<ClientForm> getAllClients() {
		try {
			List<Client> listOfClients = clientDAO.findAll();
			List<ClientForm> listOfClientForms = new ArrayList<ClientForm>();
			for(Client client : listOfClients)
				listOfClientForms.add(getClientFormFromClient(client));
			return listOfClientForms;
		} catch (PersistenceExceptionWrapper ex) {
			throw new ServiceException(ex);
		}
	}
	
	@Override
	public List<AddressForm> getAllAddressesFromClient(Long oid) throws ServiceException {
		try {
			Client client = clientDAO.findByOID(oid);
			ClientForm clientForm = getClientFormFromClient(client);
			
			List<AddressForm> addressFormList = new ArrayList<AddressForm>();
			List<Address> addressList = new ArrayList<Address>();
			
			for(Long addressOid : clientForm.getAddressOidList()) {
				Address address = addressDAO.findByOID(addressOid);
				addressList.add(address);
			}
			
			for(Address address : addressList) {
				AddressForm addressForm = new AddressForm();
				addressForm.setOid(address.getOid().toString());
				addressForm.setStreet(address.getStreet());
				addressForm.setCity(address.getCity());
				addressForm.setState(address.getState());
				addressForm.setCountry(address.getCountry());
				addressForm.setZipcode(address.getZipcode());
				addressFormList.add(addressForm);
			}
			
			return addressFormList;
		} catch (PersistenceExceptionWrapper ex) {
			throw new ServiceException(ex);
		}
	}
	
	@Override
	public Long findClientOid(ClientForm clientForm) throws ServiceException {
		try {
			Client client = getClientFromClientForm(clientForm);
			Client foundClient = 
					clientDAO.getUniqueObjectByProperties(
									new String[] {"firstName", "lastName", "telephone", "email"},
									new Object[] {client.getFirstName(), client.getLastName(), client.getTelephone(), client.getEmail() }
									);		
			return foundClient.getOid();
		} catch (PersistenceExceptionWrapper ex) {
			throw new ServiceException(ex);
		}
	}
	
	private void merge(Client client, ClientForm clientForm) {
		client.setFirstName(clientForm.getFirstName());
		client.setLastName(clientForm.getLastName());
		client.setTelephone(clientForm.getTelephone());
		client.setEmail(clientForm.getEmail());
		// TODO: Update Addresses
//		try {
//			List<Address> addressList = new ArrayList<Address>();
//			for(Long addressOid : clientForm.getAddressOidList()) {
//				Address address = addressDAO.findByOID(addressOid);
//				addressList.add(address);
//			}
//			client.setAddresses(addressList);
//		} catch (PersistenceExceptionWrapper ex) {
//			throw new ServiceException(ex);
//		}
	}

	private Client getClientFromClientForm(ClientForm clientForm) {
		Client client = new Client();
		
		client.setOid(clientForm.getOid());
		client.setFirstName(clientForm.getFirstName());
		client.setLastName(clientForm.getLastName());
		client.setTelephone(clientForm.getTelephone());
		client.setEmail(clientForm.getEmail());
		List<Address> addressList = new ArrayList<Address>();
		for(Long addressOid : clientForm.getAddressOidList()) {
			Address address = addressDAO.findByOID(addressOid);
			addressList.add(address);
		}
		client.setAddresses(addressList);
		
		return client;
	}
	
	private ClientForm getClientFormFromClient(Client client) {
		ClientForm clientForm = new ClientForm();
		
		clientForm.setOid(client.getOid());
		clientForm.setFirstName(client.getFirstName());
		clientForm.setLastName(client.getLastName());
		clientForm.setTelephone(client.getTelephone());
		clientForm.setEmail(client.getEmail());
		List<Address> addressList = client.getAddresses();
		List<Long> addressOidList = new ArrayList<Long>();
		for(Address address : addressList) {
			addressOidList.add(address.getOid());
		}
		clientForm.setAddressOidList(addressOidList);
		
		return clientForm;
	}
}
